package cn.maidouya.hrm.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
import java.util.Arrays;

/**
 *  security授权服务端和客户端授权配置
 */
@Configuration  // 告诉spring这个配置文件并交给spring管理
@EnableAuthorizationServer // 开启授权服务端支持
public class HrmAuthorizeConfig extends AuthorizationServerConfigurerAdapter {
    // 1. security安全配置
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("permitAll()")  // token放行
                // 允许客户端进行表单身份验证,使用表单认证申请令牌
                .allowFormAuthenticationForClients();
    }

    // 2. 客户端用户详情配置
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // withClientDetails提供客户端详情配置的一个服务  getClientDetailsService()方法注入用户信息
        clients.withClientDetails(getClientDetailsService());
    }
    // A、连接连接池
    @Autowired
    private DataSource dataSource;
    // B、客户端配置方法
    public ClientDetailsService getClientDetailsService(){
        // 用户信息验证
        JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
        // 用户密码调用解密器进行解密
        jdbcClientDetailsService.setPasswordEncoder(new BCryptPasswordEncoder());
        // 校验信息和密码完成返回对象数据
        return jdbcClientDetailsService;
    }


    // 3. 服务端配置
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                //  1.密码授权模式需要
                .authenticationManager(authenticationManager)
                // 2.授权码模式服务  产生code码
                // authorizationCodeServices(new JdbcAuthorizationCodeServices(dataSource))
                .authorizationCodeServices(getJdbcAuthorizationCodeServices())
                // 3.配置令牌管理服务
                .tokenServices(tokenService())
                // 允许支持的请求方式
                .allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET);
    }

    // 解密器
    @Bean
    public JdbcAuthorizationCodeServices getJdbcAuthorizationCodeServices(){
        JdbcAuthorizationCodeServices codeServices = new JdbcAuthorizationCodeServices(dataSource);
        return codeServices;
    }

    //  A、服务端配置存储token
    @Autowired
    private AuthenticationManager authenticationManager;

    //  B、配置token方式和刷新时间
    private AuthorizationServerTokenServices tokenService(){
            DefaultTokenServices token = new DefaultTokenServices();

            // 配置存储方式，1 数据库 2 内存  目前是内存
            //token.setTokenStore(new InMemoryTokenStore()); // 原生token
             token.setTokenStore(jwtTokenStore());


        //设置token增强 - 设置token转换器
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter()));
        token.setTokenEnhancer(tokenEnhancerChain);  //jwtAccessTokenConverter()

            // 存储时间7200等于两个小时
            token.setAccessTokenValiditySeconds(7200);
            // 设置是否支持刷新
            token.setSupportRefreshToken(true);
        return token;
    }

    private TokenStore jwtTokenStore() {
        JwtTokenStore jwtTokenStore = new JwtTokenStore(jwtAccessTokenConverter());
        return jwtTokenStore;
    }

    public static final String sign = "**itsource&……%￥%￥￥";

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
        tokenConverter.setSigningKey(sign);
        return tokenConverter;
    }
}